//
//  ViewController.m
//  ARPlay
//
//  Created by Hao on 2017/8/14.
//  Copyright © 2017年 Hao. All rights reserved.
//

#import "ViewController.h"
#import <CoreMotion/CoreMotion.h>

typedef NS_OPTIONS(NSUInteger, CollisionCategory) {
    CollisionCategoryBolt     = 1 << 0,
    CollisionCategorySun      = 1 << 1,
    CollisionCategoryMercury  = 1 << 2,
    CollisionCategoryVenus    = 1 << 3,
    CollisionCategoryMars     = 1 << 4,
    CollisionCategoryEarth    = 1 << 5,
    CollisionCategoryJupiter  = 1 << 6,
    CollisionCategorySaturn   = 1 << 7,
    CollisionCategoryUranus   = 1 << 8,
    CollisionCategoryNeptune  = 1 << 9,
    CollisionCategoryPluto    = 1 << 10,
};

@interface ViewController () <ARSCNViewDelegate,ARSessionDelegate,SCNPhysicsContactDelegate>

@property (nonatomic, strong) IBOutlet ARSCNView *sceneView;

//Node对象
@property(nonatomic, strong) SCNNode *sunNode;
@property(nonatomic, strong) SCNNode *earthNode;
@property(nonatomic, strong) SCNNode *moonNode;
@property(nonatomic, strong) SCNNode *marsNode; //火星
@property(nonatomic, strong) SCNNode *mercuryNode;//水星
@property(nonatomic, strong) SCNNode *venusNode;//金星
@property(nonatomic, strong) SCNNode *jupiterNode; //木星
@property(nonatomic, strong) SCNNode *jupiterLoopNode; //木星环
@property(nonatomic, strong) SCNNode *jupiterGroupNode;//木星环
@property(nonatomic, strong) SCNNode *saturnNode; //土星
@property(nonatomic, strong) SCNNode *saturnLoopNode; //土星环
@property(nonatomic, strong) SCNNode *saturnGruopNode;//土星Group
@property(nonatomic, strong) SCNNode *uranusNode; //天王星
@property(nonatomic, strong) SCNNode *uranusLoopNode; //天王星环
@property(nonatomic, strong) SCNNode *uranusGroupNode; //天王星Group
@property(nonatomic, strong) SCNNode *neptuneNode; //海王星
@property(nonatomic, strong) SCNNode *neptuneLoopNode; //海王星环
@property(nonatomic, strong) SCNNode *neptuneGroupNode; //海王星Group
@property(nonatomic, strong) SCNNode *plutoNode; //冥王星
@property(nonatomic, strong) SCNNode *earthGroupNode;
@property(nonatomic, strong) SCNNode *sunHaloNode;

@property(nonatomic, strong) SCNNode *bullet;// 武器
@property(nonatomic, strong) SCNNode *sightNode;// 准星
@property(nonatomic, strong) UIImageView *sightView;// 准星
@property(nonatomic, strong) SCNAudioSource *audio;

@property(nonatomic, strong) SCNNode *theText;
@property(nonatomic, strong) SCNNode *theScore;
@property(nonatomic, strong) UILabel *lbscore;
@property(nonatomic, strong) UILabel *lbfinished;
@property(nonatomic, strong) UILabel *lbresume;
@property(nonatomic, strong) UIButton *btnStart;

@property(nonatomic, assign) NSUInteger score;
@property(nonatomic, assign) NSUInteger sunNodeHit;
@property(nonatomic, assign) NSUInteger somNodeHit;
@property(nonatomic, assign) NSUInteger allNodeHit;
@property(nonatomic, assign) BOOL finished;


@property(nonatomic, strong) CMMotionManager *motionManager;
@property(nonatomic, strong) CMAttitude *motionAtti;
@property(nonatomic, strong) CMAttitude *initialAttitude;
@property(nonatomic, strong) UIButton * btn;
@end

    
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // Set the view's delegate
    self.sceneView.delegate = self;
    
    // Show statistics such as fps and timing information
    self.sceneView.showsStatistics = YES;
    
    // Create a new scene
//    SCNScene *scene = [SCNScene sceneNamed:@"art.scnassets/ship.scn"];
//
//    // Set the scene to the view
//    self.sceneView.scene = scene;
    _sunNodeHit = 0;
    _somNodeHit = 0;
    _allNodeHit = 9;
    [self updateScore:0];
    [self createSight];
    [self createMianScene];
//    [self createBullet];
    [self useAccelerometerPush];
    
    // gun.
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(blueGunNotification:) name:@"kBlueGunNotification" object:nil];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    
    // Create a session configuration
    ARWorldTrackingSessionConfiguration *configuration = [ARWorldTrackingSessionConfiguration new];
    configuration.worldAlignment = ARWorldAlignmentGravity;
//    configuration.planeDetection = ARPlaneDetectionHorizontal;
    configuration.lightEstimationEnabled = YES;
    
    // Run the view's session
    self.sceneView.session.delegate = self;
    self.sceneView.scene.physicsWorld.contactDelegate = self;
    [self.sceneView.session runWithConfiguration:configuration];
    
    self.audio = [SCNAudioSource audioSourceNamed:@"music_background.wav"];
    self.audio.loops = YES;
    [self.sceneView.scene.rootNode runAction:[SCNAction playAudioSource:self.audio waitForCompletion:NO]];
    
    // Add resume
    [self addResume];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    
    // Pause the view's session
    [self.sceneView.session pause];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.
}

- (void)dealloc {
    
}

#pragma mark - ARSCNViewDelegate

/*
// Override to create and configure nodes for anchors added to the view's session.
- (SCNNode *)renderer:(id<SCNSceneRenderer>)renderer nodeForAnchor:(ARAnchor *)anchor {
    SCNNode *node = [SCNNode new];
 
    // Add geometry to the node...
 
    return node;
}
*/

- (void)session:(ARSession *)session didFailWithError:(NSError *)error {
    // Present an error message to the user
    
}

- (void)sessionWasInterrupted:(ARSession *)session {
    // Inform the user that the session has been interrupted, for example, by presenting an overlay
    
}

- (void)sessionInterruptionEnded:(ARSession *)session {
    // Reset tracking and/or remove existing anchors if consistent tracking is required
    
}

#pragma mark -ARSessionDelegate
//会话位置更新
- (void)session:(ARSession *)session didUpdateFrame:(ARFrame *)frame
{
    //监听手机的移动，实现近距离查看太阳系细节，为了凸显效果变化值*3
    [_sunNode setPosition:SCNVector3Make(-3 * frame.camera.transform.columns[3].x, -0.1 - 3 * frame.camera.transform.columns[3].y, -2 - 3 * frame.camera.transform.columns[3].z)];
//    [_sunNode setPosition:SCNVector3Make(-1.2 * frame.camera.transform.columns[3].x, -0.1 - 1.2 * frame.camera.transform.columns[3].y, -2.8 - 1.2 * frame.camera.transform.columns[3].z)];
}

#pragma mark - Helper About

- (void)useAccelerometerPush {
    //初始化全局管理对象
    CMMotionManager *manager = [[CMMotionManager alloc] init];
    self.motionManager = manager;
    //判断加速度计可不可用，判断加速度计是否开启
//    if ([manager isGyroAvailable])
//    {
//        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//        //告诉manager，更新频率是100Hz
//        manager.gyroUpdateInterval = 0.01;
//        //Push方式获取和处理数据
//        [manager startGyroUpdatesToQueue:queue
//                             withHandler:^(CMGyroData *gyroData, NSError *error)
//         {
//             NSLog(@"Gyro Rotation x = %.04f", gyroData.rotationRate.x);
//             NSLog(@"Gyro Rotation y = %.04f", gyroData.rotationRate.y);
//             NSLog(@"Gyro Rotation z = %.04f", gyroData.rotationRate.z);
//             dispatch_async(dispatch_get_main_queue(), ^{
//
//             });
//
//         }];
//    }
    if ([manager isAccelerometerAvailable]) {
        [manager setDeviceMotionUpdateInterval:1/60.0f];
        __weak ViewController *weakSelf = self;
        if (manager.deviceMotionAvailable) {
            [manager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue]
                                          withHandler:^(CMDeviceMotion *data, NSError *error) {
                                              dispatch_async(dispatch_get_main_queue(), ^{
                                                  if(!weakSelf.initialAttitude) {
                                                      weakSelf.initialAttitude = manager.deviceMotion.attitude;
                                                      return;
                                                  }
                                                  weakSelf.motionAtti = data.attitude;
                                                  weakSelf.initialAttitude = manager.deviceMotion.attitude;
                                              });
                                          }];
        }
    }
}


#pragma mark - Scene About

- (void)createBullet {
    _bullet = [SCNNode new];
    
//    SCNCylinder *bCylinderNode = [SCNCylinder cylinderWithRadius:0.05 height:1];
//    SCNMaterial *material = [SCNMaterial material];
//    [[material diffuse] setContents:[SKColor yellowColor]];
//    material.diffuse.intensity = 60;
//    material.emission.contents = [SKColor yellowColor];
//    material.lightingModelName = SCNLightingModelConstant;
//    [bCylinderNode setMaterials:@[material]];
//    _bullet.geometry = bCylinderNode;
    
    SCNSphere *sphere = [SCNSphere sphereWithRadius:0.25];
    sphere.firstMaterial.diffuse.contents = [SKColor yellowColor];
    _bullet.geometry = sphere;
    
    [_bullet setPosition:SCNVector3Make(0, 0, -10)];
    
    _bullet.physicsBody = [SCNPhysicsBody dynamicBody];//[SCNPhysicsBody bodyWithType:SCNPhysicsBodyTypeDynamic shape:shape];//[SCNPhysicsBody bodyWithType:SCNPhysicsBodyTypeDynamic shape:nil];
    _bullet.physicsBody.mass = 2.0;
    _bullet.physicsBody.affectedByGravity = NO;
    _bullet.physicsBody.categoryBitMask = CollisionCategorySun;
    _bullet.physicsBody.collisionBitMask = 0x0;
    _bullet.physicsBody.contactTestBitMask = CollisionCategoryBolt;
    
    [self.sceneView.scene.rootNode addChildNode:_bullet];
    
//    [self.sceneView.scene.rootNode addChildNode:_bullet];
    
    
//    CAKeyframeAnimation * anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
//    anim.values = @ [
//                     [NSValue valueWithSCNVector3:SCNVector3Make(0,0,0)],
//                     [NSValue valueWithSCNVector3:SCNVector3Make(0,0,-10)],
//                     [NSValue valueWithSCNVector3:SCNVector3Make(0,0,-20)],
//                     [NSValue valueWithSCNVector3:SCNVector3Make(0,0,-30)],
//                     ];
//    [_bullet addAnimation:anim forKey:@"orbit"];
}

- (void)createSight {
//    _sightNode = [SCNNode new];
//    _sightNode.opacity = 0.8;
//    _sightNode.geometry = [SCNBox boxWithWidth:0 height:0.2 length:0.2 chamferRadius:0];
//    _sightNode.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/sun.png";
//    _sightNode.geometry.firstMaterial.diffuse.mipFilter = SCNFilterModeLinear;
//    _sightNode.rotation = SCNVector4Make(1, 1, 1, M_PI_2);
//    _sightNode.geometry.firstMaterial.lightingModelName = SCNLightingModelConstant; // no lighting
//
//    [_sightNode setPosition:SCNVector3Make(0, 0, -1)];
//
//    [self.sceneView.scene.rootNode addChildNode:_sightNode];
    
    _sightView = [UIImageView new];
//    _sightView.image = [UIImage imageNamed:@"protect"];
    _sightView.center = self.sceneView.center;
    _sightView.backgroundColor = [UIColor redColor];
    _sightView.bounds = CGRectMake(0, 0, 20, 20);
    _sightView.hidden = YES;
    [self.sceneView addSubview:_sightView];
}

- (void)createNodes {
    @autoreleasepool {
        _sunNode = [SCNNode new];
        _mercuryNode = [SCNNode new];
        _venusNode = [SCNNode new];
        _earthNode = [SCNNode new];
        _moonNode = [SCNNode new];
        _marsNode = [SCNNode new];
        _earthGroupNode = [SCNNode new];
        _jupiterNode = [SCNNode new];
        _saturnNode = [SCNNode new];
        _saturnGruopNode = [SCNNode new];
        _uranusNode = [SCNNode new];
        _neptuneNode = [SCNNode new];
        _plutoNode = [SCNNode new];
    }
}

- (void)createGeometry {
    @autoreleasepool {
        _sunNode.geometry           = [SCNSphere sphereWithRadius:0.25];
        _mercuryNode.geometry       = [SCNSphere sphereWithRadius:0.08];
        _venusNode.geometry         = [SCNSphere sphereWithRadius:0.12];
        _marsNode.geometry          = [SCNSphere sphereWithRadius:0.11];
        _earthNode.geometry         = [SCNSphere sphereWithRadius:0.13];
        _moonNode.geometry          = [SCNSphere sphereWithRadius:0.05];
        _jupiterNode.geometry       = [SCNSphere sphereWithRadius:0.23];
        _saturnNode.geometry        = [SCNSphere sphereWithRadius:0.20];
        _uranusNode.geometry        = [SCNSphere sphereWithRadius:0.17];
        _neptuneNode.geometry       = [SCNSphere sphereWithRadius:0.16];
        _plutoNode.geometry         = [SCNSphere sphereWithRadius:0.12];
        
        _mercuryNode.position       = SCNVector3Make(0.36, 0, 0);
        _venusNode.position         = SCNVector3Make(0.63, 0, -0.4);
        _marsNode.position          = SCNVector3Make(-0.86, 0, -0.7);
        _earthGroupNode.position    = SCNVector3Make(1.15, 0, -0.9);
        _jupiterNode.position       = SCNVector3Make(1.85, 0, -0.3);
        _saturnGruopNode.position   = SCNVector3Make(-2.28, 0, -0.6);
        _uranusNode.position        = SCNVector3Make(2.68, 0, -0.2);
        _neptuneNode.position       = SCNVector3Make(-2.98, 0, -0.5);
        _plutoNode.position         = SCNVector3Make(3.288, 0, -0.8);
        _moonNode.position          = SCNVector3Make(0.23, 0, 0);
        
        _sunNode.position           = SCNVector3Make(0, 0, -3);
    }
}

- (void)addEffectToNode {
    @autoreleasepool {
        //添加土星环
        SCNNode *saturnLoopNode = [SCNNode new];
        saturnLoopNode.opacity = 0.4;
        saturnLoopNode.geometry = [SCNBox boxWithWidth:0.6 height:0 length:0.6 chamferRadius:0];
        saturnLoopNode.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/saturn_loop.png";
        saturnLoopNode.geometry.firstMaterial.diffuse.mipFilter = SCNFilterModeLinear;
        saturnLoopNode.rotation = SCNVector4Make(-0.5, -1, 0, M_PI_2);
        saturnLoopNode.geometry.firstMaterial.lightingModelName = SCNLightingModelConstant; // no lighting
        [_saturnGruopNode addChildNode:saturnLoopNode];
        
        //水星贴图
        _mercuryNode.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/mercury.jpg";
        //金星贴图
        _venusNode.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/venus.jpg";
        //火星贴图
        _marsNode.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/mars.jpg";
        
        // 地球贴图
        _earthNode.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/earth-diffuse-mini.jpg";
        _earthNode.geometry.firstMaterial.emission.contents = @"art.scnassets/earth/earth-emissive-mini.jpg";
        _earthNode.geometry.firstMaterial.specular.contents = @"art.scnassets/earth/earth-specular-mini.jpg";
        //月球贴图
        _moonNode.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/moon.jpg";
        
        //木星贴图
        _jupiterNode.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/jupiter.jpg";
        //土星贴图
        _saturnNode.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/saturn.jpg";
        _saturnLoopNode.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/saturn_loop.jpg";
        //天王星
        _uranusNode.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/uranus.jpg";
        //海王星
        _neptuneNode.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/neptune.jpg";
        //冥王星
        _plutoNode.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/pluto.jpg";
        
        //太阳贴图
        _sunNode.geometry.firstMaterial.multiply.contents = @"art.scnassets/earth/sun.jpg";
        _sunNode.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/sun.jpg";
        _sunNode.geometry.firstMaterial.multiply.intensity = 0.5;
        _sunNode.geometry.firstMaterial.lightingModelName = SCNLightingModelConstant;
        
        _sunNode.geometry.firstMaterial.multiply.wrapS =
        _sunNode.geometry.firstMaterial.diffuse.wrapS  =
        _sunNode.geometry.firstMaterial.multiply.wrapT =
        _sunNode.geometry.firstMaterial.diffuse.wrapT  = SCNWrapModeRepeat;
        
        _mercuryNode.geometry.firstMaterial.locksAmbientWithDiffuse =
        _venusNode.geometry.firstMaterial.locksAmbientWithDiffuse =
        _marsNode.geometry.firstMaterial.locksAmbientWithDiffuse =
        _earthNode.geometry.firstMaterial.locksAmbientWithDiffuse =
        _moonNode.geometry.firstMaterial.locksAmbientWithDiffuse  =
        _jupiterNode.geometry.firstMaterial.locksAmbientWithDiffuse  =
        _saturnNode.geometry.firstMaterial.locksAmbientWithDiffuse  =
        _uranusNode.geometry.firstMaterial.locksAmbientWithDiffuse  =
        _neptuneNode.geometry.firstMaterial.locksAmbientWithDiffuse  =
        _plutoNode.geometry.firstMaterial.locksAmbientWithDiffuse  =
        _sunNode.geometry.firstMaterial.locksAmbientWithDiffuse   = YES;
        
        _mercuryNode.geometry.firstMaterial.shininess =
        _venusNode.geometry.firstMaterial.shininess =
        _earthNode.geometry.firstMaterial.shininess =
        _moonNode.geometry.firstMaterial.shininess =
        _marsNode.geometry.firstMaterial.shininess =
        _jupiterNode.geometry.firstMaterial.shininess =
        _saturnNode.geometry.firstMaterial.shininess =
        _uranusNode.geometry.firstMaterial.shininess =
        _neptuneNode.geometry.firstMaterial.shininess =
        _plutoNode.geometry.firstMaterial.shininess = 0.1;
        
        _mercuryNode.geometry.firstMaterial.specular.intensity =
        _venusNode.geometry.firstMaterial.specular.intensity =
        _earthNode.geometry.firstMaterial.specular.intensity =
        _moonNode.geometry.firstMaterial.specular.intensity =
        _marsNode.geometry.firstMaterial.specular.intensity =
        _jupiterNode.geometry.firstMaterial.specular.intensity =
        _saturnNode.geometry.firstMaterial.specular.intensity =
        _uranusNode.geometry.firstMaterial.specular.intensity =
        _neptuneNode.geometry.firstMaterial.specular.intensity =
        _plutoNode.geometry.firstMaterial.specular.intensity =
        _marsNode.geometry.firstMaterial.specular.intensity = 0.5;
        
        _moonNode.geometry.firstMaterial.specular.contents = [UIColor grayColor];
    }
}

- (void)addChildNode {
    @autoreleasepool {
        [_earthGroupNode addChildNode:_earthNode];
        [_saturnGruopNode addChildNode:_saturnNode];
    }
}

- (void)createMianScene {
    
    [self createNodes];
    [self createGeometry];
    [self addEffectToNode];
    [self addPhysicsBody];
    [self addChildNode];
    
    [self roationNode];
    [self addAnimationToSun];
    [self addOtherNode];
    [self addLight];
    
    
    [self.sceneView.scene.rootNode addChildNode:_sunNode];
    
}

- (void)addPhysicsBody {
    @autoreleasepool {
        _sunNode.physicsBody = [SCNPhysicsBody dynamicBody];
        _sunNode.physicsBody.mass = 10.0;
        _sunNode.physicsBody.affectedByGravity = NO;
        _sunNode.physicsBody.categoryBitMask = CollisionCategorySun;
        _sunNode.physicsBody.collisionBitMask = 0x0;
        _sunNode.physicsBody.contactTestBitMask = CollisionCategoryBolt;
        
        _mercuryNode.physicsBody = [SCNPhysicsBody kinematicBody];
        _mercuryNode.physicsBody.mass = 3.0;
        _mercuryNode.physicsBody.affectedByGravity = NO;
        _mercuryNode.physicsBody.categoryBitMask = CollisionCategoryMercury;
        _mercuryNode.physicsBody.collisionBitMask = 0x0;
        _mercuryNode.physicsBody.contactTestBitMask = CollisionCategoryBolt;
        
        _venusNode.physicsBody = [SCNPhysicsBody kinematicBody];
        _venusNode.physicsBody.mass = 6.0;
        _venusNode.physicsBody.affectedByGravity = NO;
        _venusNode.physicsBody.categoryBitMask = CollisionCategoryVenus;
        _venusNode.physicsBody.collisionBitMask = 0x0;
        _venusNode.physicsBody.contactTestBitMask = CollisionCategoryBolt;
        
        _marsNode.physicsBody = [SCNPhysicsBody kinematicBody];
        _marsNode.physicsBody.mass = 5.0;
        _marsNode.physicsBody.affectedByGravity = NO;
        _marsNode.physicsBody.categoryBitMask = CollisionCategoryMars;
        _marsNode.physicsBody.collisionBitMask = 0x0;
        _marsNode.physicsBody.contactTestBitMask = CollisionCategoryBolt;
        
        _earthGroupNode.physicsBody = [SCNPhysicsBody kinematicBody];
        _earthGroupNode.physicsBody.mass = 4.0;
        _earthGroupNode.physicsBody.affectedByGravity = NO;
        _earthGroupNode.physicsBody.categoryBitMask = CollisionCategoryEarth;
        _earthGroupNode.physicsBody.collisionBitMask = 0x0;
        _earthGroupNode.physicsBody.contactTestBitMask = CollisionCategoryBolt;
        
        
        _jupiterNode.physicsBody = [SCNPhysicsBody kinematicBody];
        _jupiterNode.physicsBody.mass = 11.0;
        _jupiterNode.physicsBody.affectedByGravity = NO;
        _jupiterNode.physicsBody.categoryBitMask = CollisionCategoryJupiter;
        _jupiterNode.physicsBody.collisionBitMask = 0x0;
        _jupiterNode.physicsBody.contactTestBitMask = CollisionCategoryBolt;
        
        _saturnNode.physicsBody = [SCNPhysicsBody kinematicBody];
        _saturnNode.physicsBody.mass = 5.0;
        _saturnNode.physicsBody.affectedByGravity = NO;
        _saturnNode.physicsBody.categoryBitMask = CollisionCategorySaturn;
        _saturnNode.physicsBody.collisionBitMask = 0x0;
        _saturnNode.physicsBody.contactTestBitMask = CollisionCategoryBolt;
        
        _uranusNode.physicsBody = [SCNPhysicsBody kinematicBody];
        _uranusNode.physicsBody.mass = 7.0;
        _uranusNode.physicsBody.affectedByGravity = NO;
        _uranusNode.physicsBody.categoryBitMask = CollisionCategoryUranus;
        _uranusNode.physicsBody.collisionBitMask = 0x0;
        _uranusNode.physicsBody.contactTestBitMask = CollisionCategoryBolt;
        
        _neptuneNode.physicsBody = [SCNPhysicsBody kinematicBody];
        _neptuneNode.physicsBody.mass = 6.0;
        _neptuneNode.physicsBody.affectedByGravity = NO;
        _neptuneNode.physicsBody.categoryBitMask = CollisionCategoryNeptune;
        _neptuneNode.physicsBody.collisionBitMask = 0x0;
        _neptuneNode.physicsBody.contactTestBitMask = CollisionCategoryBolt;
        
        _plutoNode.physicsBody = [SCNPhysicsBody kinematicBody];
        _plutoNode.physicsBody.mass = 8.0;
        _plutoNode.physicsBody.affectedByGravity = NO;
        _plutoNode.physicsBody.categoryBitMask = CollisionCategoryPluto;
        _plutoNode.physicsBody.collisionBitMask = 0x0;
        _plutoNode.physicsBody.contactTestBitMask = CollisionCategoryBolt;
    }
}

- (void)roationNode {
    
    @autoreleasepool {
        // Rotate self
        [_mercuryNode runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0 y:2 z:0 duration:1]]];
        [_venusNode runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0 y:2 z:0 duration:1]]];
        [_marsNode runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0 y:2 z:0 duration:1]]];
        [_earthNode runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0 y:2 z:0 duration:1]]];
        [_jupiterNode runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0 y:2 z:0 duration:1]]];
        [_saturnNode runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0 y:2 z:0 duration:1]]];
        [_uranusNode runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0 y:2 z:0 duration:1]]];
        [_neptuneNode runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0 y:2 z:0 duration:1]]];
        [_plutoNode runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0 y:2 z:0 duration:1]]];
        
        // Rotate the Mercury
        SCNNode *mercRotationNode = [SCNNode node];
        [mercRotationNode addChildNode:_mercuryNode];
        
        // Rotate the Mercury around the Sun
        CABasicAnimation *mercAnimation = [CABasicAnimation animationWithKeyPath:@"rotation"];
        mercAnimation.duration = 3.0;
        mercAnimation.toValue = [NSValue valueWithSCNVector4:SCNVector4Make(0, 1, 0, M_PI * 2)];
        mercAnimation.repeatCount = FLT_MAX;
        [mercRotationNode addAnimation:mercAnimation forKey:@"mercury rotation around sun"];
        [_sunNode addChildNode:mercRotationNode];
        
        
        // Rotate the venus
        SCNNode *venusRotationNode = [SCNNode node];
        [venusRotationNode addChildNode:_venusNode];
        
        // Rotate the Venus around the Sun
        CABasicAnimation *vensAnimation = [CABasicAnimation animationWithKeyPath:@"rotation"];
        vensAnimation.duration = 7.0;
        vensAnimation.toValue = [NSValue valueWithSCNVector4:SCNVector4Make(0, 1, 0, M_PI * 2)];
        vensAnimation.repeatCount = FLT_MAX;
        [venusRotationNode addAnimation:vensAnimation forKey:@"venus rotation around sun"];
        [_sunNode addChildNode:venusRotationNode];
        
        
        // Totate the Mars
        SCNNode *marsRotationNode = [SCNNode node];
        [marsRotationNode addChildNode:_marsNode];
        
        // Rotate the Mars around the Sun
        CABasicAnimation *marsAnimation = [CABasicAnimation animationWithKeyPath:@"rotation"];
        marsAnimation.duration = 4.0;
        marsAnimation.toValue = [NSValue valueWithSCNVector4:SCNVector4Make(0, 1, 0, M_PI * 2)];
        marsAnimation.repeatCount = FLT_MAX;
        [marsRotationNode addAnimation:marsAnimation forKey:@"mars rotation around sun"];
        [_sunNode addChildNode:marsRotationNode];
        
        
        // Rotate the moon
        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"rotation"];        //月球自转
        animation.duration = 1.5;
        animation.toValue = [NSValue valueWithSCNVector4:SCNVector4Make(0, 1, 0, M_PI * 2)];
        animation.repeatCount = FLT_MAX;
        [_moonNode addAnimation:animation forKey:@"moon rotation"];
        
        // Moon-rotation (center of rotation of the Moon around the Earth)
        SCNNode *moonRotationNode = [SCNNode node];
        [moonRotationNode addChildNode:_moonNode];
        
        // Rotate the moon around the Earth
        CABasicAnimation *moonRotationAnimation = [CABasicAnimation animationWithKeyPath:@"rotation"];
        moonRotationAnimation.duration = 4.0;
        moonRotationAnimation.toValue = [NSValue valueWithSCNVector4:SCNVector4Make(0, 1, 0, M_PI * 2)];
        moonRotationAnimation.repeatCount = FLT_MAX;
        [moonRotationNode addAnimation:animation forKey:@"moon rotation around earth"];
        [_earthGroupNode addChildNode:moonRotationNode];
        
        [_earthGroupNode addChildNode:_earthNode];
        // Earth-rotation (center of rotation of the Earth around the Sun)
        SCNNode *earthRotationNode = [SCNNode node];
        // Earth-group (will contain the Earth, and the Moon)
        [earthRotationNode addChildNode:_earthGroupNode];
        
        // Rotate the Earth around the Sun
        CABasicAnimation *earthAnimation = [CABasicAnimation animationWithKeyPath:@"rotation"];
        earthAnimation.duration = 6.0;
        earthAnimation.toValue = [NSValue valueWithSCNVector4:SCNVector4Make(0, 1, 0, M_PI * 2)];
        earthAnimation.repeatCount = FLT_MAX;
        [earthRotationNode addAnimation:earthAnimation forKey:@"earth rotation around sun"];
        [_sunNode addChildNode:earthRotationNode];
        
        
        // Rotate the Jupiter
        SCNNode *jupiterRotationNode = [SCNNode node];
        [jupiterRotationNode addChildNode:_jupiterNode];
        [_sunNode addChildNode:jupiterRotationNode];
        
        // Rotate the Jupiter around the Sun
        CABasicAnimation *jptAnimation = [CABasicAnimation animationWithKeyPath:@"rotation"];
        jptAnimation.duration = 12.0;
        jptAnimation.toValue = [NSValue valueWithSCNVector4:SCNVector4Make(0, 1, 0, M_PI * 2)];
        jptAnimation.repeatCount = FLT_MAX;
        [jupiterRotationNode addAnimation:jptAnimation forKey:@"jupiter rotation around sun"];
        [_sunNode addChildNode:jupiterRotationNode];
        
        
        
        // Rotate the Saturn
        SCNNode *saturnRotationNode = [SCNNode node];
        [saturnRotationNode addChildNode:_saturnGruopNode];
        
        // Rotate the Saturn around the Sun
        CABasicAnimation *satAnimation = [CABasicAnimation animationWithKeyPath:@"rotation"];
        satAnimation.duration = 9.0;
        satAnimation.toValue = [NSValue valueWithSCNVector4:SCNVector4Make(0, 1, 0, M_PI * 2)];
        satAnimation.repeatCount = FLT_MAX;
        [saturnRotationNode addAnimation:satAnimation forKey:@"mars rotation around sun"];
        [_sunNode addChildNode:saturnRotationNode];
        
        
        // Rotate the Uranus
        SCNNode *uranusRotationNode = [SCNNode node];
        [uranusRotationNode addChildNode:_uranusNode];
        
        // Rotate the uranus around the Sun
        CABasicAnimation *unsAnimation = [CABasicAnimation animationWithKeyPath:@"rotation"];
        unsAnimation.duration = 16.0;
        unsAnimation.toValue = [NSValue valueWithSCNVector4:SCNVector4Make(0, 1, 0, M_PI * 2)];
        unsAnimation.repeatCount = FLT_MAX;
        [uranusRotationNode addAnimation:unsAnimation forKey:@"mars rotation around sun"];
        [_sunNode addChildNode:uranusRotationNode];
        
        
        // Rotate the Nepturn
        SCNNode *neptuneRotationNode = [SCNNode node];
        [neptuneRotationNode addChildNode:_neptuneNode];
        
        // Rotate the Neptune around the Sun
        CABasicAnimation *nptAnimation = [CABasicAnimation animationWithKeyPath:@"rotation"];
        nptAnimation.duration = 6.0;
        nptAnimation.toValue = [NSValue valueWithSCNVector4:SCNVector4Make(0, 1, 0, M_PI * 2)];
        nptAnimation.repeatCount = FLT_MAX;
        [neptuneRotationNode addAnimation:nptAnimation forKey:@"mars rotation around sun"];
        [_sunNode addChildNode:neptuneRotationNode];
        
        
        // Rotate the Pluto
        SCNNode *plutoRotationNode = [SCNNode node];
        [plutoRotationNode addChildNode:_plutoNode];
        
        // Rotate the Pluto around the Sun
        CABasicAnimation *ptoAnimation = [CABasicAnimation animationWithKeyPath:@"rotation"];
        ptoAnimation.duration = 12.0;
        ptoAnimation.toValue = [NSValue valueWithSCNVector4:SCNVector4Make(0, 1, 0, M_PI * 2)];
        ptoAnimation.repeatCount = FLT_MAX;
        [plutoRotationNode addAnimation:ptoAnimation forKey:@"mars rotation around sun"];
        [_sunNode addChildNode:plutoRotationNode];
    }
    
}

- (void)addAnimationToSun {
    
    @autoreleasepool {
        // Achieve a lava effect by animating textures
        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"contentsTransform"];
        animation.duration = 5.0;
        animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DConcat(CATransform3DMakeTranslation(0, 0, 0), CATransform3DMakeScale(3, 3, 3))];
        animation.toValue = [NSValue valueWithCATransform3D:CATransform3DConcat(CATransform3DMakeTranslation(1, 0, 0), CATransform3DMakeScale(3, 3, 3))];
        animation.repeatCount = FLT_MAX;
        [_sunNode.geometry.firstMaterial.diffuse addAnimation:animation forKey:@"sun-texture"];
        
        animation = [CABasicAnimation animationWithKeyPath:@"contentsTransform"];
        animation.duration = 20.0;
        animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DConcat(CATransform3DMakeTranslation(0, 0, 0), CATransform3DMakeScale(5, 5, 5))];
        animation.toValue = [NSValue valueWithCATransform3D:CATransform3DConcat(CATransform3DMakeTranslation(1, 0, 0), CATransform3DMakeScale(5, 5, 5))];
        animation.repeatCount = FLT_MAX;
        [_sunNode.geometry.firstMaterial.multiply addAnimation:animation forKey:@"sun-texture2"];
        
    }
}

- (void)addOtherNode {
    
    @autoreleasepool {
        
        SCNNode *cloudsNode = [SCNNode node];
        cloudsNode.geometry = [SCNSphere sphereWithRadius:0.18];
        [_earthNode addChildNode:cloudsNode];
        
        cloudsNode.opacity = 0.5;
        // This effect can also be achieved with an image with some transparency set as the contents of the 'diffuse' property
        cloudsNode.geometry.firstMaterial.transparent.contents = @"art.scnassets/earth/cloudsTransparency.png";
        cloudsNode.geometry.firstMaterial.transparencyMode = SCNTransparencyModeRGBZero;
        
        // Add a halo to the Sun (a simple textured plane that does not write to depth)
        _sunHaloNode = [SCNNode node];
        _sunHaloNode.geometry = [SCNPlane planeWithWidth:2.5 height:2.5];
        _sunHaloNode.rotation = SCNVector4Make(1, 0, 0, 0 * M_PI / 180.0);
        _sunHaloNode.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/sun-halo.png";
        _sunHaloNode.geometry.firstMaterial.lightingModelName = SCNLightingModelConstant; // no lighting
        _sunHaloNode.geometry.firstMaterial.writesToDepthBuffer = NO; // do not write to depth
        _sunHaloNode.opacity = 0.2;
        [_sunNode addChildNode:_sunHaloNode];
        
        // Add a textured plane to represent mercury's orbit
        SCNNode *mercuryOrbit = [SCNNode node];
        mercuryOrbit.opacity = 0.4;
        mercuryOrbit.geometry = [SCNBox boxWithWidth:0.8 height:0 length:0.8 chamferRadius:0];
        mercuryOrbit.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/orbit.png";
        mercuryOrbit.geometry.firstMaterial.diffuse.mipFilter = SCNFilterModeLinear;
        mercuryOrbit.rotation = SCNVector4Make(0, 1, 0, M_PI_2);
        mercuryOrbit.geometry.firstMaterial.lightingModelName = SCNLightingModelConstant; // no lighting
        [_sunNode addChildNode:mercuryOrbit];
        
        // Add a textured plane to represent venus's orbit
        SCNNode *venusOrbit = [SCNNode node];
        venusOrbit.opacity = 0.4;
        venusOrbit.geometry = [SCNBox boxWithWidth:1.6 height:0 length:1.6 chamferRadius:0];
        venusOrbit.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/orbit.png";
        venusOrbit.geometry.firstMaterial.diffuse.mipFilter = SCNFilterModeLinear;
        venusOrbit.rotation = SCNVector4Make(0, 1, 0, M_PI_2);
        venusOrbit.geometry.firstMaterial.lightingModelName = SCNLightingModelConstant; // no lighting
        [_sunNode addChildNode:venusOrbit];
        
        // Add a textured plane to represent Earth's orbit
        SCNNode *earthOrbit = [SCNNode node];
        earthOrbit.opacity = 0.4;
        earthOrbit.geometry = [SCNBox boxWithWidth:2.4 height:0 length:2.4 chamferRadius:0];
        earthOrbit.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/orbit.png";
        earthOrbit.geometry.firstMaterial.diffuse.mipFilter = SCNFilterModeLinear;
        earthOrbit.rotation = SCNVector4Make(0, 1, 0, M_PI_2);
        earthOrbit.geometry.firstMaterial.lightingModelName = SCNLightingModelConstant; // no lighting
        [_sunNode addChildNode:earthOrbit];
        
        // Add a textured plane to represent mars's orbit
        SCNNode *marsOrbit = [SCNNode node];
        marsOrbit.opacity = 0.4;
        marsOrbit.geometry = [SCNBox boxWithWidth:3.2 height:0 length:3.2 chamferRadius:0];
        marsOrbit.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/orbit.png";
        marsOrbit.geometry.firstMaterial.diffuse.mipFilter = SCNFilterModeLinear;
        marsOrbit.rotation = SCNVector4Make(0, 1, 0, M_PI_2);
        marsOrbit.geometry.firstMaterial.lightingModelName = SCNLightingModelConstant; // no lighting
        [_sunNode addChildNode:marsOrbit];
        
        // Add a textured plane to represent jupiter's orbit
        SCNNode *jupiterOrbit = [SCNNode node];
        jupiterOrbit.opacity = 0.4;
        jupiterOrbit.geometry = [SCNBox boxWithWidth:4.0 height:0 length:4.0 chamferRadius:0];
        jupiterOrbit.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/orbit.png";
        jupiterOrbit.geometry.firstMaterial.diffuse.mipFilter = SCNFilterModeLinear;
        jupiterOrbit.rotation = SCNVector4Make(0, 1, 0, M_PI_2);
        jupiterOrbit.geometry.firstMaterial.lightingModelName = SCNLightingModelConstant; // no lighting
        [_sunNode addChildNode:jupiterOrbit];
        
        // Add a textured plane to represent saturn's orbit
        SCNNode *saturnOrbit = [SCNNode node];
        saturnOrbit.opacity = 0.4;
        saturnOrbit.geometry = [SCNBox boxWithWidth:4.96 height:0 length:4.96 chamferRadius:0];
        saturnOrbit.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/orbit.png";
        saturnOrbit.geometry.firstMaterial.diffuse.mipFilter = SCNFilterModeLinear;
        saturnOrbit.rotation = SCNVector4Make(0, 1, 0, M_PI_2);
        saturnOrbit.geometry.firstMaterial.lightingModelName = SCNLightingModelConstant; // no lighting
        [_sunNode addChildNode:saturnOrbit];
        
        // Add a textured plane to represent uranus's orbit
        SCNNode *uranusOrbit = [SCNNode node];
        uranusOrbit.opacity = 0.4;
        uranusOrbit.geometry = [SCNBox boxWithWidth:5.76 height:0 length:5.76 chamferRadius:0];
        uranusOrbit.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/orbit.png";
        uranusOrbit.geometry.firstMaterial.diffuse.mipFilter = SCNFilterModeLinear;
        uranusOrbit.rotation = SCNVector4Make(0, 1, 0, M_PI_2);
        uranusOrbit.geometry.firstMaterial.lightingModelName = SCNLightingModelConstant; // no lighting
        [_sunNode addChildNode:uranusOrbit];
        
        // Add a textured plane to represent neptune's orbit
        SCNNode *neptuneOrbit = [SCNNode node];
        neptuneOrbit.opacity = 0.4;
        neptuneOrbit.geometry = [SCNBox boxWithWidth:6.48 height:0 length:6.48 chamferRadius:0];
        neptuneOrbit.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/orbit.png";
        neptuneOrbit.geometry.firstMaterial.diffuse.mipFilter = SCNFilterModeLinear;
        neptuneOrbit.rotation = SCNVector4Make(0, 1, 0, M_PI_2);
        neptuneOrbit.geometry.firstMaterial.lightingModelName = SCNLightingModelConstant; // no lighting
        [_sunNode addChildNode:neptuneOrbit];
        
        // Add a textured plane to represent plute's orbit
        SCNNode *pluteOrbit = [SCNNode node];
        pluteOrbit.opacity = 0.4;
        pluteOrbit.geometry = [SCNBox boxWithWidth:7.28 height:0 length:7.28 chamferRadius:0];
        pluteOrbit.geometry.firstMaterial.diffuse.contents = @"art.scnassets/earth/orbit.png";
        pluteOrbit.geometry.firstMaterial.diffuse.mipFilter = SCNFilterModeLinear;
        pluteOrbit.rotation = SCNVector4Make(0, 1, 0, M_PI_2);
        pluteOrbit.geometry.firstMaterial.lightingModelName = SCNLightingModelConstant; // no lighting
        [_sunNode addChildNode:pluteOrbit];
    }
    
}

- (void)addLight {
    
    @autoreleasepool {
        // We will turn off all the lights in the scene and add a new light
        // to give the impression that the Sun lights the scene
        SCNNode *lightNode = [SCNNode node];
        lightNode.light = [SCNLight light];
        lightNode.light.color = [UIColor blackColor]; // initially switched off
        lightNode.light.type = SCNLightTypeOmni;
        [_sunNode addChildNode:lightNode];
        
        // Configure attenuation distances because we don't want to light the floor
        lightNode.light.attenuationEndDistance = 19;
        lightNode.light.attenuationStartDistance = 21;
        
        // Animation
        [SCNTransaction begin];
        [SCNTransaction setAnimationDuration:1];
        {
            lightNode.light.color = [UIColor whiteColor]; // switch on
            //[presentationViewController updateLightingWithIntensities:@[@0.0]]; //switch off all the other lights
            _sunHaloNode.opacity = 0.5; // make the halo stronger
        }
        [SCNTransaction commit];
    }
}


#pragma mark - Gesture Recognizers

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {
    UITouch *touch = touches.allObjects.firstObject;
//    CGPoint location = [touch locationInView:self.sceneView];
//    NSArray *hitResults = [self.sceneView hitTest:location options:nil];
//    if (hitResults && [hitResults count] > 0) {
//        SCNHitTestResult *result = [hitResults firstObject];
//        [self dispatchHitTest:result];
//    }
    UIView *hitGes = touch.view;
    if (hitGes && [hitGes isKindOfClass:[UILabel class]]) {
        _finished = YES;
        [_sunNode removeFromParentNode];
        [self performSelectorOnMainThread:@selector(gameStart) withObject:nil waitUntilDone:NO];
        return;
    }
    [[NSNotificationCenter defaultCenter] postNotificationName:@"kBlueGunNotification" object:@"EYBleGunCommandTypeTrigger"];
}

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {
    
}

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {
    
}

- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {
    
}

- (void)touchesEstimatedPropertiesUpdated:(NSSet<UITouch *> *)touches {
    
}

- (void)dispatchHitTest:(SCNHitTestResult *)hit {
    SCNNode *node = hit.node;
    [self handleHitTest:node];
}

- (void)handleHitTest:(SCNNode *)node {
    @autoreleasepool {
    if (_theText && [node isEqual:_theText]) {
        SCNParticleSystem *exp = [SCNParticleSystem new];
        exp.loops = NO;
        exp.birthRate = 5000;
        exp.emissionDuration = 0.01;
        exp.spreadingAngle = 180;
        exp.particleDiesOnCollision = YES;
        exp.particleLifeSpan = 0.5;
        exp.particleLifeSpanVariation = 0.3;
        exp.particleVelocity = 500;
        exp.particleVelocityVariation = 5;
        exp.particleSize = 0.2;
        exp.stretchFactor = 0.3;
        exp.particleColor = [UIColor redColor];
        [node addParticleSystem:exp];
        
        [self performSelector:@selector(gameStart) withObject:node afterDelay:0.02];
        return;
    }
    
    BOOL hited = NO;
    if ([node.geometry isKindOfClass:[SCNSphere class]]) {
        SCNSphere *sphere = (SCNSphere *)node.geometry;
        if (sphere.radius == 0.18) {
            hited = YES;
        }
    }
    
    if (!hited && ([node isEqual:_earthGroupNode]
        || [node isEqual:_earthNode]
        || [node isEqual:_marsNode]
        || [node isEqual:_mercuryNode]
        || [node isEqual:_venusNode]
        || [node isEqual:_jupiterNode]
        || [node isEqual:_saturnNode]
        || [node isEqual:_uranusNode]
        || [node isEqual:_neptuneNode]
        || [node isEqual:_plutoNode]
        || [node isEqual:_jupiterGroupNode]
        || [node isEqual:_saturnGruopNode]
        || [node isEqual:_uranusGroupNode]
        || [node isEqual:_neptuneGroupNode])) {
        
        _somNodeHit++;
        if (_somNodeHit == 50) {
            hited = YES;
        } else {
            [self performSelectorOnMainThread:@selector(updateScore:) withObject:@(10) waitUntilDone:NO];
        }
    }
    
    if (!hited && [node isEqual:_sunNode]) {
        _sunNodeHit++;
        if (_sunNodeHit == 200) {
            hited = YES;
        } else {
            [self performSelectorOnMainThread:@selector(updateScore:) withObject:@(10) waitUntilDone:NO];
        }
    }
    
    if (_score >= 2000 || hited) {
        SCNParticleSystem *exp = [SCNParticleSystem new];
        exp.loops = NO;
        exp.birthRate = 5000;
        exp.emissionDuration = 0.01;
        exp.spreadingAngle = 180;
        exp.particleDiesOnCollision = YES;
        exp.particleLifeSpan = 0.5;
        exp.particleLifeSpanVariation = 0.3;
        exp.particleVelocity = 500;
        exp.particleVelocityVariation = 5;
        exp.particleSize = 0.2;
        exp.stretchFactor = 0.3;
        exp.particleColor = [UIColor redColor];
//        exp.particleImage = [UIImage imageNamed:@"part_flash_dff.tif"];
        [node addParticleSystem:exp];
        
        [self.sceneView.scene.rootNode runAction:[SCNAction playAudioSource:[SCNAudioSource audioSourceNamed:@"explosion_player.wav"] waitForCompletion:NO]];
//        [self performSelector:@selector(removeHit:) withObject:node afterDelay:0.02];
        [self performSelectorOnMainThread:@selector(removeHit:) withObject:node waitUntilDone:NO];
    }
    }
}

- (void)removeHit:(SCNNode *)node {
    
    @autoreleasepool {
    node.hidden = YES;
    _allNodeHit--;
    
    if ([node.geometry isKindOfClass:[SCNSphere class]]) {
        SCNSphere *sphere = (SCNSphere *)node.geometry;
        if (sphere.radius == 0.18) {
            [_earthGroupNode removeFromParentNode];
            [_earthNode removeFromParentNode];
            [_moonNode removeFromParentNode];
        }
    }
    if ([node isEqual:_earthGroupNode]) {
        [_earthGroupNode removeFromParentNode];
        [_earthNode removeFromParentNode];
        [_moonNode removeFromParentNode];
    }
    if ([node isEqual:_marsNode]) {
        [_marsNode removeFromParentNode];
    }
    if ([node isEqual:_mercuryNode]) {
        [_mercuryNode removeFromParentNode];
    }
    if ([node isEqual:_jupiterNode] || [node isEqual:_jupiterGroupNode]) {
        [_jupiterNode removeFromParentNode];
        [_jupiterLoopNode removeFromParentNode];
        [_jupiterGroupNode removeFromParentNode];
    }
    if ([node isEqual:_saturnGruopNode] || [node isEqual:_saturnNode]) {
        [_saturnLoopNode removeFromParentNode];
        [_saturnNode removeFromParentNode];
        [_saturnGruopNode removeFromParentNode];
    }
    if ([node isEqual:_uranusGroupNode] || [node isEqual:_uranusNode]) {
        [_uranusNode removeFromParentNode];
        [_uranusLoopNode removeFromParentNode];
        [_uranusGroupNode removeFromParentNode];
    }
    if ([node isEqual:_neptuneGroupNode] || [node isEqual:_neptuneNode]) {
        [_neptuneLoopNode removeFromParentNode];
        [_neptuneNode removeFromParentNode];
        [_neptuneGroupNode removeFromParentNode];
    }
    [node removeAllParticleSystems];
    [node removeFromParentNode];
    
    [self performSelectorOnMainThread:@selector(updateScore:) withObject:@(10) waitUntilDone:NO];
    if (_allNodeHit == 0 || _sunNodeHit >= 200 || _score >= 2000) {
        // GAME OVER
        [_sunNode removeFromParentNode];
        _finished = YES;
        [self performSelectorOnMainThread:@selector(gameOver) withObject:nil waitUntilDone:NO];
    }
    }
}

- (void)updateScore:(NSNumber *)thsscore {
//    if (_theScore) {
//        [_theScore removeFromParentNode];
//        _theScore = nil;
//    }
//    _score += score;
//    NSString *s = [NSString stringWithFormat:@"SCORE: %lu.",_score];
//    SCNText *text = [SCNText textWithString:s extrusionDepth:1];
//    text.chamferRadius = 0.5;
//    text.flatness = 0.3;
//    text.font = [UIFont systemFontOfSize:5];
//    text.firstMaterial.specular.contents = [UIColor yellowColor];
//    text.firstMaterial.diffuse.contents = [UIColor blueColor];
//    text.firstMaterial.shininess = 0.4;
//    _theScore = [SCNNode nodeWithGeometry:text];
//    _theScore.scale = SCNVector3Make(0.4, 0.4, 0.4);
//    [_theScore setPosition:SCNVector3Make(-20, -5, -60)];
//    [self.sceneView.scene.rootNode addChildNode:_theScore];
    int score = [thsscore intValue];
    if (!_lbscore) {
        _lbscore = [UILabel new];
        _lbscore.font = [UIFont fontWithName:@"Trebuchet-BoldItalic" size:16];
        _lbscore.frame = CGRectMake(5, 0, 300, 44);
        _lbscore.textColor = [UIColor redColor];
        _lbscore.textAlignment = NSTextAlignmentLeft;
        [self.sceneView addSubview:_lbscore];
    }
    if (_score < 2000) {
        _score += score;
    }
    dispatch_async(dispatch_get_main_queue(), ^{
        _lbscore.text = [NSString stringWithFormat:@"SCORE: %lu",_score];
    });
}

- (void)addTap {
    UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(gameStart)];
    recognizer.numberOfTouchesRequired = 1;
    recognizer.numberOfTapsRequired = 1;
    [_lbfinished addGestureRecognizer:recognizer];
}

- (void)gameOver {
    NSLog(@"GAME OVER.");
    
//    SCNText *text = [SCNText textWithString:@"GAME OVER" extrusionDepth:5];
//    text.chamferRadius = 0.5;
//    text.flatness = 0.3;
//    text.font = [UIFont systemFontOfSize:8];
//    text.firstMaterial.specular.contents = [UIColor redColor];
//    text.firstMaterial.diffuse.contents = [UIColor yellowColor];
//    text.firstMaterial.shininess = 0.4;
//    _theText = [SCNNode nodeWithGeometry:text];
//    _theText.scale = SCNVector3Make(0.6, 0.6, 0.6);
//    [_theText setPosition:SCNVector3Make(0, 0, -20)];
//    [self.sceneView.scene.rootNode addChildNode:_theText];
    
    if (!_lbfinished) {
        _lbfinished = [UILabel new];
        _lbfinished.font = [UIFont fontWithName:@"Trebuchet-BoldItalic" size:32];
        _lbfinished.frame = CGRectMake(0, 0, 300, 120);
        _lbfinished.textColor = [UIColor redColor];
        _lbfinished.center = self.sceneView.center;
        _lbfinished.textAlignment = NSTextAlignmentCenter;
        _lbfinished.userInteractionEnabled = YES;
        _lbfinished.multipleTouchEnabled = YES;
        [self.sceneView addSubview:_lbfinished];
        [self addTap];
    }
    [_lbfinished setHidden:NO];
    _lbfinished.text = @"GAME OVER";
}

- (void)gameStart {
    
    @autoreleasepool {
    
    if (!_finished) {
        return;
    }
    SCNParticleSystem *exp = [SCNParticleSystem new];
    exp.loops = NO;
    exp.birthRate = 5000;
    exp.emissionDuration = 0.01;
    exp.spreadingAngle = 180;
    exp.particleDiesOnCollision = YES;
    exp.particleLifeSpan = 0.5;
    exp.particleLifeSpanVariation = 0.3;
    exp.particleVelocity = 500;
    exp.particleVelocityVariation = 5;
    exp.particleSize = 0.2;
    exp.stretchFactor = 0.3;
    exp.particleColor = [UIColor redColor];
    [self.sceneView.scene.rootNode addParticleSystem:exp];
    [self.sceneView.scene.rootNode removeAllParticleSystems];
    
    [_theText removeFromParentNode];
    [_lbfinished setHidden:YES];
    _finished = NO;
    _score = 0;
    _sunNodeHit = 0;
    _somNodeHit = 0;
    _allNodeHit = 9;
    [self updateScore:0];
    [self createMianScene];
    
    ARWorldTrackingSessionConfiguration *configuration = [ARWorldTrackingSessionConfiguration new];
    configuration.worldAlignment = ARWorldAlignmentGravity;
//    configuration.planeDetection = ARPlaneDetectionHorizontal;
    configuration.lightEstimationEnabled = YES;
    
    self.sceneView.session.delegate = self;
    self.sceneView.scene.physicsWorld.contactDelegate = self;
    [self.sceneView.session runWithConfiguration:configuration options:ARSessionRunOptionResetTracking];
        
    }
}

- (void)addResume {
    if (!_lbresume) {
        _lbresume = [UILabel new];
        _lbresume.font = [UIFont fontWithName:@"Trebuchet-BoldItalic" size:16];
        _lbresume.frame = CGRectMake(5, 44, 100, 44);
        _lbresume.textColor = [UIColor redColor];
        _lbresume.textAlignment = NSTextAlignmentLeft;
        _lbresume.userInteractionEnabled = YES;
        _lbresume.multipleTouchEnabled = YES;
        _lbresume.text = @"RESUME";
        [self.sceneView addSubview:_lbresume];
        [self addTap];
    }
}

#pragma mark - SCNPhysicsContactDelegate

- (void)physicsWorld:(SCNPhysicsWorld *)world didBeginContact:(SCNPhysicsContact *)contact {
    NSLog(@"CONTACT");
    SCNNode *boltNode,*enmyNode;
    if (contact.nodeA.physicsBody.categoryBitMask == CollisionCategoryBolt) {
        boltNode = contact.nodeA;
        enmyNode = contact.nodeB;
    } else if (contact.nodeB.physicsBody.categoryBitMask == CollisionCategoryBolt) {
        enmyNode = contact.nodeA;
        boltNode = contact.nodeB;
    }
    NSLog(@"%@",enmyNode);
    [boltNode setHidden:YES];
    if (enmyNode) {
        [self handleHitTest:enmyNode];
    }
}

- (void)physicsWorld:(SCNPhysicsWorld *)world didUpdateContact:(SCNPhysicsContact *)contact {
    NSLog(@"CONTACT");
}

- (void)physicsWorld:(SCNPhysicsWorld *)world didEndContact:(SCNPhysicsContact *)contact {
    NSLog(@"CONTACT");
}

#pragma mark - Gun

- (void)blueGunNotification:(NSNotification*)data {
    @autoreleasepool {
        if (data.object) {
            
            NSLog(@"Notifiaction: %@",data.object);
            if ([@"EYBleGunCommandTypeLeftFront" isEqualToString:data.object]) {
                [self performSelectorOnMainThread:@selector(gameStart) withObject:nil waitUntilDone:NO];
                return;
            }
            if ([@"EYBleGunCommandTypeLeftBack" isEqualToString:data.object]) {
                _finished = YES;
                [_sunNode removeFromParentNode];
                [self performSelectorOnMainThread:@selector(gameStart) withObject:nil waitUntilDone:NO];
                return;
            }
            if (_finished) {
                return;
            }
            
            
            [self.sceneView.scene.rootNode runAction:[SCNAction playAudioSource:[SCNAudioSource audioSourceNamed:@"weapon_player.wav"] waitForCompletion:NO]];
            matrix_float4x4 mfloat4x4 = SCNMatrix4ToMat4(_sunNode.worldTransform);
            NSLog(@"x:%f-y:%f,z:%f",mfloat4x4.columns[3].x,mfloat4x4.columns[3].y,mfloat4x4.columns[3].z);
            
            // pitch是X周方向的转动，增加的时候表示设备正朝你倾斜，减少的时候表示疏远；
            // roll是Y轴的转向，值减少的时候表示正往左边转，增加的时候往右；
            // yaw是Z轴转向，减少是时候是顺时针，增加的时候是逆时针。
            float width  = self.sceneView.bounds.size.width / 2;
            float height = self.sceneView.bounds.size.width / 2;
            float y,temp;
            if(self.motionAtti.roll < -M_PI_2 || self.motionAtti.roll > M_PI_2) {
//                y = width * sin(self.motionAtti.pitch);
                temp = width * cos(-self.motionAtti.pitch);
            } else {
//                y = width * sin(-self.motionAtti.pitch);
                temp = width * cos(self.motionAtti.pitch);
            }
            y = height * self.motionAtti.roll;
//            float x = -width * self.motionAtti.pitch;
//            float z = -temp * cos(self.motionAtti.roll);
            NSLog(@"x:%f,y:%f,z:%f",self.motionAtti.pitch,self.motionAtti.roll,self.motionAtti.yaw);
//            GLKVector3 vec = GLKVector3Make(x, y, 0);
//            GLKMatrix4 mat = GLKMatrix4MakeRotation(self.motionAtti.yaw, 0, 0, 30);
//            vec = GLKMatrix4MultiplyVector3(mat, vec);
//            [node runAction:[SCNAction sequence:@[[SCNAction rotateToX: self.motionAtti.pitch y:self.motionAtti.roll z:self.motionAtti.yaw duration:0],[SCNAction duration:0.2],[SCNAction removeFromParentNode]]]];
//            NSLog(@"E: %f",_earthNode.worldPosition.x);
//            [node runAction:[SCNAction sequence:@[[SCNAction rotateToX:self.motionAtti.pitch y:0 z:0 duration:0],[SCNAction moveTo:SCNVector3Make(self.motionAtti.pitch,0,-12) duration:0.5],[SCNAction removeFromParentNode]]]];
            
            
            //            SCNBox *box = [SCNBox boxWithWidth:0.9 height:0.9 length:0.9 chamferRadius:5];
            //            box.firstMaterial.diffuse.contents = [UIColor redColor];
            SCNSphere *spehre = [SCNSphere sphereWithRadius:0.06];
            spehre.firstMaterial.diffuse.contents = [UIColor redColor];
            SCNNode *node = [SCNNode nodeWithGeometry:spehre];
            node.name = [NSString stringWithFormat:@"%ld",(NSInteger)[[NSDate date] timeIntervalSince1970]*1000];
            node.physicsBody = [SCNPhysicsBody dynamicBody];//[SCNPhysicsBody bodyWithType:SCNPhysicsBodyTypeDynamic shape:[SCNPhysicsShape shapeWithNode:node options:nil]];
            node.physicsBody.categoryBitMask = CollisionCategoryBolt;
            node.physicsBody.collisionBitMask = 0x0;
            node.physicsBody.contactTestBitMask = CollisionCategorySun|CollisionCategoryMercury|CollisionCategoryVenus|CollisionCategoryMars|CollisionCategoryEarth|CollisionCategoryJupiter|CollisionCategorySaturn|CollisionCategoryUranus|CollisionCategoryNeptune|CollisionCategoryPluto;
//            node.position = SCNVector3Make(self.motionAtti.pitch, -0.1, 0.5*self.motionAtti.yaw);
            node.position = SCNVector3Make(self.motionAtti.pitch, -0.1, -mfloat4x4.columns[3].z);//0.5*self.motionAtti.yaw
            node.physicsBody.affectedByGravity = NO;
            [self.sceneView.scene.rootNode addChildNode:node];
            
            
//            [node runAction:[SCNAction sequence:@[[SCNAction rotateToX:-self.motionAtti.pitch y:self.motionAtti.roll z:self.motionAtti.yaw duration:0],[SCNAction moveTo:SCNVector3Make(-self.motionAtti.pitch, mfloat4x4.columns[3].y,-4 - 1.2 * self.motionAtti.yaw) duration:0.8],[SCNAction removeFromParentNode]]]];
            
            
//            [node runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:10*self.motionAtti.pitch y:1.0 z:0 duration:0.1]]];
//            [node runAction:[SCNAction sequence:
//  @[[SCNAction moveTo:SCNVector3Make(50*self.motionAtti.pitch, mfloat4x4.columns[3].y,-3 - 1.2 * self.motionAtti.yaw) duration:0.5],
//    [SCNAction rotateByX:50*self.motionAtti.pitch y:1.0 z:-3 - 1.2 * self.motionAtti.yaw duration:0.4],
//    [SCNAction removeFromParentNode]]]];
            
            
            [node runAction:[SCNAction sequence:@[[SCNAction rotateByX:mfloat4x4.columns[3].x y:-0.1 z:-mfloat4x4.columns[3].z duration:0]]]];
            [node runAction:[SCNAction sequence:
                             @[[SCNAction moveTo:SCNVector3Make(-2*mfloat4x4.columns[3].x, mfloat4x4.columns[3].y,4*mfloat4x4.columns[3].z) duration:0.5],
                               [SCNAction rotateByX:-2*mfloat4x4.columns[3].x y:1.0 z:4*mfloat4x4.columns[3].z duration:0],
                               [SCNAction removeFromParentNode]]]];
            
            
            //            NSLog(@"E: %f",_earthNode.worldPosition.x);
            
//            dispatch_async(dispatch_get_main_queue(), ^{
//                float i_x = width + x;
//                float i_y = height + y;
//                CGPoint point = CGPointMake(i_x, i_y);
//                self.sightView.center = point;
//                [UIView animateWithDuration:0.1 animations:^{
//                    self.sightView.hidden = NO;
//                } completion:^(BOOL finished) {
//                    [self hitTestWithPosition:self.motionAtti.pitch andY:self.motionAtti.roll];
//                    [self performSelector:@selector(refreshSight) withObject:nil afterDelay:0.1];
//                }];
//            });
            
//            dispatch_async(dispatch_get_main_queue(), ^{
//                self.lbscore.text = [NSString stringWithFormat:@"SUN: x:0.%f,y:%f,z:%f;GRY: x:0.%f,y:%f,z:%f",mfloat4x4.columns[3].x,mfloat4x4.columns[3].y,mfloat4x4.columns[3].z,self.motionAtti.pitch,self.motionAtti.roll,self.motionAtti.yaw];
//            });
            
        }
    }
}

- (void)refreshSight {
    self.sightView.hidden = YES;
}

- (void)hitTestWithPosition:(float)x andY:(float)y {
    matrix_float4x4 efloat4x4 = SCNMatrix4ToMat4(_earthNode.worldTransform);
    matrix_float4x4 mfloat4x4 = SCNMatrix4ToMat4(_sunNode.worldTransform);
    NSLog(@"x:%f-y:%f,z:%f",efloat4x4.columns[3].x,efloat4x4.columns[3].y,efloat4x4.columns[3].z);
    NSLog(@"x:%f-y:%f,z:%f",mfloat4x4.columns[3].x,mfloat4x4.columns[3].y,mfloat4x4.columns[3].z);
//    float f_x = fabsf(x);
//    if (f_x < 0.02) {
//        [self handleHitTest:_sunNode];
//    } else if (f_x < 0.2) {
//        [self handleHitTest:_mercuryNode];
//    } else if (f_x < 0.3) {
//        [self handleHitTest:_venusNode];
//    } else if (f_x < 0.4) {
//        [self handleHitTest:_marsNode];
//    } else if (f_x < 0.5) {
//        [self handleHitTest:_earthNode];
//    } else if (f_x < 0.6) {
//        [self handleHitTest:_jupiterNode];
//    } else if (f_x < 0.7) {
//        [self handleHitTest:_saturnNode];
//    } else if (f_x < 0.8) {
//        [self handleHitTest:_uranusNode];
//    } else if (f_x < 0.9) {
//        [self handleHitTest:_neptuneNode];
//    } else if (f_x < 0.9) {
//        [self handleHitTest:_plutoNode];
//    }
}

@end
